<template>
  <div class="hello" ref="three">
    <!-- <img src="../../public/assets/kt_b.jpg" alt=""> -->
  </div>
</template>

<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
let scene = null
let camera = null
let renderer = null
let cube = null
let sphere = null
let sprite = null

export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data() {
    return {}
  },
  mounted() {
    window.removeEventListener('click', this.GoToRoom)
    this.init()
  },
  methods: {
    init() {
      // 初始化场景
      this.initScene()
      // 初始化相机
      this.initcamera()
      // 构建渲染器
      this.initRenderer()
      // 创建立方体
      this.createCube()
      // 创建球体
      // this.createSphere()
      // 添加房屋模型
      // this.loadRoomModel()
      // 添加光源
      this.addLight()
      // 交互点
      // this.createSprite()
      // 渲染循环
      this.render()
      // 初始化事件
      this.initEvent()
    },
    initScene() {
      scene = new THREE.Scene()
    },
    initcamera() {
      camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
      camera.position.z = 0.5
      // camera.position.y = 10
      // camera.position.x = 10
    },
    initRenderer() {
      renderer = new THREE.WebGLRenderer()
      renderer.setSize(window.innerWidth, window.innerHeight)
      // 添加控制器
      this.initControls(renderer.domElement)
      // 将渲染元素添加到页面
      this.$refs.three.appendChild(renderer.domElement)
    },
    createCube() {
      const geometry = new THREE.BoxGeometry(10, 10, 10)
      const colors = [
        { color: 0xff0000 },
        { color: 0x00ff00 },
        { color: 0x0000ff },
        { color: 0xff00ff },
        { color: 0xffff00 },
        { color: 0x00ffff }
      ]
      const material = []
      for (let i = 0, len = colors.length; i < len; i++) {
        material.push(new THREE.MeshBasicMaterial(colors[i]))
      }
      // 纹理贴图
      // const material = this.texture()
      cube = new THREE.Mesh(geometry, material)
      // 内外翻转
      // cube.geometry.scale(1, 1, -1)
      scene.add(cube)
    },
    texture() {
      // 左右、上下、后前
      const urls = [
        'http://cdn.huodao.hk/upload_img/20220620/3e532822bd445485d27677ca55a79b10.jpg?proportion=1',
        'http://cdn.huodao.hk/upload_img/20220620/cebf6fbcafdf4f5c945e0881418e34ec.jpg?proportion=1',
        'http://cdn.huodao.hk/upload_img/20220620/273081d1896fc66866842543090916d3.jpg?proportion=1',
        'http://cdn.huodao.hk/upload_img/20220620/8747f61fd2215aa748dd2afb6dce3822.jpg?proportion=1',
        'http://cdn.huodao.hk/upload_img/20220620/c34262935511d61b2e9f456b689f5c1c.jpg?proportion=1',
        'http://cdn.huodao.hk/upload_img/20220620/722d2bf88f6087800ddf116511b51e73.jpg?proportion=1'
      ]
      const material = []
      for (let i = 0, len = urls.length; i < len; i++) {
        const texture = new THREE.TextureLoader().load(urls[i])
        if (i == 2 || i == 3) {
          texture.rotation = Math.PI
          texture.center = new THREE.Vector2(0.5, 0.5)
        }
        material.push(new THREE.MeshBasicMaterial({ map: texture }))
      }
      return material
    },
    createSphere() {
      const url =
        'http://cdn.huodao.hk/upload_img/20220621/6bd594e62ea5654c03d7b82718443751.png?proportion=1.99'
      const geometry = new THREE.SphereGeometry(5, 32, 32)
      const texture = new THREE.TextureLoader().load(url)
      const material = new THREE.MeshBasicMaterial({ map: texture })
      sphere = new THREE.Mesh(geometry, material)
      sphere.geometry.scale(1, 1, -1)
      scene.add(sphere)
    },
    createSprite() {
      const url =
        'http://cdn.huodao.hk/upload_img/20220621/1eca2b6efe7aab01d42ca45345f46a90.png?proportion=0.98'
      const texture = new THREE.TextureLoader().load(url)
      const material = new THREE.SpriteMaterial({ map: texture })
      sprite = new THREE.Sprite(material)

      // 设置大小、位置、内容
      sprite.scale.set(0.5, 0.5, 0.5)
      sprite.position.set(0.4, 0, -4.5)
      sprite.content = {
        title: '串门',
        to: '小明家',
        isComeAround: true
      }

      // 加入场景中
      scene.add(sprite)
    },
    loadRoomModel() {
      const loader = new FBXLoader()
      loader.load('/assets/untitled.fbx', (fbx) => {
        console.log('fbx--', fbx)
        fbx.scale.set(0.01, 0.01, 0.01)
        scene.add(fbx)
      })
    },
    addLight() {
      // 添加半球光源 -- 户外效果
      const light = new THREE.HemisphereLight(0xffffff, 0x444444)
      light.position.set(0, 200, 0)
      scene.add(light)
    },
    render() {
      renderer.render(scene, camera)
      requestAnimationFrame(this.render)
    },
    initControls(container) {
      const controls = new OrbitControls(camera, container)
      controls.enableDamping = true
      controls.maxDistance = 50
    },
    GoToRoom(e) {
      e.preventDefault()
      const { clientX, clientY } = e
      const dom = renderer.domElement
      // 拿到canvas画布到屏幕的距离
      const domRect = dom.getBoundingClientRect()
      // 计算标准设备坐标
      const x = ((clientX - domRect.left) / dom.clientWidth) * 2 - 1
      const y = -((clientY - domRect.top) / dom.clientHeight) * 2 + 1
      console.log(
        '计算标准设备坐标--',
        clientX,
        clientY,
        x,
        y,
        domRect,
        dom.clientWidth,
        dom.clientHeight
      )
      const vector = new THREE.Vector3(x, y)
      // 转世界坐标
      const worldVector = vector.unproject(camera)
      console.log('转世界坐标', worldVector)
      // 射线
      const ray = worldVector.sub(camera.position).normalize()
      // 射线投射对象
      const raycaster = new THREE.Raycaster(camera.position, ray)
      raycaster.camera = camera

      //返回射线选中的对象 //第一个参数是检测的目标对象 第二个参数是目标对象的子元素
      const intersects = raycaster.intersectObjects(scene.children)

      if (intersects.length > 0) {
        console.log('捕获到对象', intersects)
        const intersect = intersects[0]
        if (intersect.object?.type == 'Sprite' && intersect.object?.content?.isComeAround) {
          // 清除当前房间和精灵模型
          scene.remove(sphere)
          scene.remove(sprite)
          if (intersect.object?.content?.to == '小明家') {
            cube = cube || this.createCube()
            scene.add(cube)
          }
        }
      } else {
        console.log('没捕获到对象')
      }
    },
    initEvent() {
      window.addEventListener('click', this.GoToRoom)
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped></style>
